using CfgTable;
using Cysharp.Threading.Tasks;
using IQIGame.Onigao.Framework;
using IQIGame.Onigao.Game;
using IQIGame.Onigao.GameAOT;
using System;
using System.Collections.Generic;
using UnityEngine;

namespace IQIGame.Onigao.GamePlay
{
    public class UIInteractOption : UIEntityWindow
    {
        public enum ResultType
        {
            Default = 0,
            Quest = 1,
            StoryDialog = 2
        }

        public struct Result
        {
            public ResultType type;
            public int index;
            public bool isCanceled;
        }

        /// <summary>
        /// 静态配置
        /// </summary>
        private static UICreateConfig _createConfig = new()
        {
            prefabName = nameof(UIInteractOption),
            layer = EUILayer.Main,
        };

        #region Template Generate,don't modify
        protected class UIB_UIInteractOption
        {
            #region ObjectBinding Generate
            public UnityEngine.GameObject OptionItemSrc { protected set; get; }
            public UnityEngine.RectTransform ItemContainer { protected set; get; }
            public IQIGame.Onigao.Framework.ExButton closeBtn { protected set; get; }
            public virtual void InitBinding(ObjectBinding __binding)
            {
                __binding.TryGetVariableValue<UnityEngine.GameObject>("OptionItemSrc", out var __tbv0);
                this.OptionItemSrc = __tbv0;
                __binding.TryGetVariableValue<UnityEngine.RectTransform>("ItemContainer", out var __tbv1);
                this.ItemContainer = __tbv1;
                __binding.TryGetVariableValue<IQIGame.Onigao.Framework.ExButton>("closeBtn", out var __tbv2);
                this.closeBtn = __tbv2;
            }
            #endregion ObjectBinding Generate 
        }
        #endregion Template Generate,don't modify

        protected UIB_UIInteractOption ui { get; set; }

        /// <summary>
        /// 创建UI的配置
        /// </summary>
        public override IUICreateConfig createConfig => _createConfig;

        private UIMsgDispatcher uiMsgDispatcher => this._msgDispatcher as UIMsgDispatcher;

        private UIItemPool<UIN_InteractOptionItem> _optionItemPool;
        private List<UIN_InteractOptionItem> _curItems = new();
        private AutoResetUniTaskCompletionSource<(ResultType, int)> _completeTaskSource;
        private Action<ResultType, int> _callTaskComplete;

        protected override void BeforeInit()
        {
            ui = new UIB_UIInteractOption();
            ui.InitBinding(this.csObjBind);
        }

        protected override void OnInit()
        {
            _callTaskComplete = CallTaskComplete;
            _optionItemPool = this.InitPool<UIN_InteractOptionItem>(this.ui.OptionItemSrc);
        }

        protected override void OnShow(UIBaseData data)
        {

        }

        protected override void OnHide()
        {
            if (_completeTaskSource != null)
            {
                var ts = _completeTaskSource;
                _completeTaskSource = null;
                ts.TrySetCanceled();
            }
            foreach (var item in _curItems)
            {
                _optionItemPool.HideOne(item);
            }
        }

        public async UniTask<Result> ShowOptions(List<int> questList, List<int> dialogList, CfgEntityInteractType interactCfg, Vector3 worldRootPos)
        {
            //创建等待任务
            _completeTaskSource = AutoResetUniTaskCompletionSource<(ResultType, int)>.Create();
            _curItems.Clear();
            //创建任务按钮
            for (int i = 0; i < questList.Count; i++)
            {
                int questCid = questList[i];
                var cfgQuest = TableCenter.quest.Get(questCid);
                var optionItem = _optionItemPool.GetOne();
                string optionText = string.IsNullOrEmpty(cfgQuest.Name) ? "Quest.Name is null." : cfgQuest.Name;
                optionItem.SetData(ResultType.Quest, i, optionText, _callTaskComplete);
                optionItem.gameObject.transform.SetParent(ui.ItemContainer, false);
                _curItems.Add(optionItem);
            }
            //创建对话按钮
            for (int i = 0; i < dialogList.Count; i++)
            {
                int dialogCid = dialogList[i];
                var cfgDialog = TableCenter.storyDialog.Get(dialogCid);
                var optionItem = _optionItemPool.GetOne();
                string optionText = string.IsNullOrEmpty(cfgDialog.NpcSelectionName) ? "StoryDialog.NpcSelectionName is null." : cfgDialog.NpcSelectionName;
                optionItem.SetData(ResultType.StoryDialog, i, optionText, _callTaskComplete);
                optionItem.gameObject.transform.SetParent(ui.ItemContainer, false);
                _curItems.Add(optionItem);
            }
            //默认交互按钮
            var interactItem = _optionItemPool.GetOne();
            interactItem.gameObject.transform.SetParent(ui.ItemContainer, false);
            interactItem.SetData(ResultType.Default, -1, interactCfg.Name, _callTaskComplete);
            _curItems.Add(interactItem);

            Vector2 rootPos = ManagerCenter.UI.World2UIPosition(worldRootPos);
            ui.ItemContainer.localPosition = rootPos;

            Result result = default;
            try
            {
                (ResultType type, int index) = await _completeTaskSource.Task;
                result.type = type;
                result.index = index;
                Close();
            }
            catch (OperationCanceledException)
            {
                result.type = ResultType.Default;
                result.index = 0;
                result.isCanceled = true;
            }
            catch (Exception e)
            {
                result.type = ResultType.Default;
                result.index = 0;
                result.isCanceled = true;
                LogGame.LogException(e);
            }

            return result;
        }

        private void CallTaskComplete(ResultType type, int index)
        {
            if (_completeTaskSource != null)
            {
                // 注意！这里要先置空，再调用，TrySetResult会先调用await之后的代码，如果await之后有给TaskSource赋新值，然后这里再置空，那么_completeActTaskSource就永远为null了
                var ts = _completeTaskSource;
                _completeTaskSource = null;
                ts.TrySetResult((type, index));
            }
        }

        protected override void AddUGUIListener()
        {
            ui.closeBtn.AddClickEvent(OnClickCloseBtn);
        }

        protected override void AddMsgListeners()
        {
            uiMsgDispatcher.AddListener<float>(MsgEventType.EntityStartMove, OnEntityStartMove);
        }

        private void OnClickCloseBtn()
        {
            Close();
        }

        private void OnEntityStartMove(float stickPower)
        {
            Close();
        }

        protected override void OnDispose()
        {
        }
    }
}
